import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

// 创建 axios 实例
const instance = axios.create({
    baseURL: '/api', // 基础路径
    timeout: 10000, // 超时时间
});

// 请求队列
const requestQueue: Set<string> = new Set();

// 请求拦截器
instance.interceptors.request.use(
    (config: AxiosRequestConfig) => {
        // 防止重复请求
        const requestKey = `${config.method}:${config.url}`;
        if (requestQueue.has(requestKey)) {
            return Promise.reject(new Error('重复请求'));
        }
        requestQueue.add(requestKey);

        // 添加 token
        const token = localStorage.getItem('token');
        if (token) {
            config.headers = {
                ...config.headers,
                Authorization: `Bearer ${token}`,
            };
        }

        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

// 响应拦截器
instance.interceptors.response.use(
    (response: AxiosResponse) => {
        // 请求完成后移除队列中的请求
        const requestKey = `${response.config.method}:${response.config.url}`;
        requestQueue.delete(requestKey);

        return response.data;
    },
    async (error) => {
        const originalRequest = error.config;

        // 如果 token 过期，尝试刷新 token
        if (error.response?.status === 401 && !originalRequest._retry) {
            originalRequest._retry = true;
            try {
                const refreshToken = localStorage.getItem('refreshToken');
                const { data } = await axios.post('/auth/refresh-token', { refreshToken });
                localStorage.setItem('token', data.token);
                originalRequest.headers.Authorization = `Bearer ${data.token}`;
                return instance(originalRequest);
            } catch (refreshError) {
                console.error('刷新 token 失败', refreshError);
                // 清除 token 并跳转到登录页
                localStorage.removeItem('token');
                localStorage.removeItem('refreshToken');
                window.location.href = '/login';
            }
        }

        // 请求完成后移除队列中的请求
        const requestKey = `${error.config.method}:${error.config.url}`;
        requestQueue.delete(requestKey);

        return Promise.reject(error);
    }
);

// 封装请求方法
export const http = {
    get<T = any>(url: string, params?: any, config?: AxiosRequestConfig): Promise<T> {
        return instance.get(url, { params, ...config });
    },
    post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
        return instance.post(url, data, { ...config });
    },
    put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
        return instance.put(url, data, { ...config });
    },
    delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
        return instance.delete(url, { ...config });
    },
};

export default http;